package com.www.conversionspring;

import com.sun.tools.javac.util.StringUtils;
import com.www.conversionspring.beans.*;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.SpelCompilerMode;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.util.CollectionUtils;

import java.time.Instant;
import java.util.*;

/**
 * <p>
 * </p>
 *
 * @author Zed.Yun
 * @Title: SpelApplicationContext
 * @ProjectName conversion-spring
 * @date 2019/3/19 10:06
 */
@SpringBootApplication
public class SpelApplicationContext {
    public static void main(String[] args) throws NoSuchMethodException {
        Company company = new Company();
        company.setName("oracle");
        ExpressionParser expressionParser = new SpelExpressionParser();
        Expression name = expressionParser.parseExpression("name");
        String value = name.getValue(company,String.class);

        //#########################Type Conversion##############################
        Mobile mobile = new Mobile();
        SpelExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
        parser.parseExpression("price").setValue(context, mobile, "12");
        System.out.println(mobile.getPrice());
        //#########################Parser Configuration##############################
        SpelParserConfiguration spelParserConfiguration = new SpelParserConfiguration(true, true);
        SpelExpressionParser configSpelExpressionParser = new SpelExpressionParser(spelParserConfiguration);
        Expression expression = configSpelExpressionParser.parseExpression("list[3]");
        ListWrapper listWrapper  = new ListWrapper();
        String configListIndexVal = expression.getValue(listWrapper, String.class);
        configListIndexVal = "this is a joke";
        String configListIndexVal2 = expression.getValue(listWrapper, String.class);
        Expression list = configSpelExpressionParser.parseExpression("list");
        List<String> orignalList = (List<String>) list.getValue(listWrapper);
        orignalList.add("hello");
        Expression list2Expression = configSpelExpressionParser.parseExpression("list");
        List<String> checkConfigList = list2Expression.getValue(listWrapper, List.class);
        checkConfigList.stream().forEach(item-> System.out.println(item));
        //####################SpEL Compilation#########################
        SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.MIXED,
                orignalList.getClass().getClassLoader());

        SpelExpressionParser spelExpressionParser = new SpelExpressionParser(config);

        Expression expr = spelExpressionParser.parseExpression("payload");

        MyMessage message = new MyMessage();
        message.setPayload("hello spring expression language");
        List<Instant> instants = new ArrayList<>();
        Long small = null;
        Instant smallInstant = null;
        Long big = null;
        Instant bignstant = null;
        Integer i = 0;
        while(i< 100000){
            Instant from = Instant.now();
            Object payload = expr.getValue(message);
            Instant to = Instant.now();
            long runtime = to.getNano() - from.getNano();
            instants.add(to);
            if(small == null || small >= runtime){
                small = runtime;
                smallInstant = to;
            }
            if(big == null || big <= runtime){
                big = runtime;
                bignstant = to;
            }
            i++;
        }
        int smallIndex = instants.indexOf(smallInstant);
        System.out.println("在"+smallIndex+"出现最短时间"+small);

        int bigIndex = instants.indexOf(bignstant);
        System.out.println("在"+bigIndex+"出现最长时间"+big);

        //####################4.3.7. Operators#########################
        Company companyOprator = new Company();
        ExpressionParser companyOpratorParser = new SpelExpressionParser();
        EvaluationContext companyOpratorContext = SimpleEvaluationContext.forReadWriteDataBinding().build();
        companyOpratorParser.parseExpression("name =  'hello'").getValue(companyOpratorContext, companyOprator);
        System.out.println(companyOprator);


        Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);
        System.out.println(dateClass);

        Company sunCompany = parser.parseExpression("new com.www.conversionspring.beans.Company('sun')").getValue(Company.class);
        System.out.println(sunCompany);


        //#######################4.3.10. Variables################################
        EvaluationContext variableContext = SimpleEvaluationContext.forReadWriteDataBinding().build();
        variableContext.setVariable("content","i want to go Massachusetts Institute of Technology");
        ExpressionParser variableParser =  new SpelExpressionParser();
        Company myCompany = new Company();
        variableParser.parseExpression("name = #content").getValue(variableContext , myCompany);
        System.out.println(myCompany);
        //#######################4.3.11. Functions################################
        EvaluationContext methodContext = SimpleEvaluationContext.forReadOnlyDataBinding().build();
        methodContext.setVariable("nameLen", CompanyFunction.class.getDeclaredMethod("nameLen",String.class));
        ExpressionParser functionParser = new SpelExpressionParser();
        functionParser.parseExpression("#nameLen('abc')").getValue(methodContext);


    }
}

